// 08_enums_and_pattern_matching.rs
// 演示 Rust 中的枚举与模式匹配

// 1. 定义枚举
// 枚举允许我们定义一个类型，该类型可以是几个不同变体中的一个
enum IpAddrKind {
    V4,
    V6,
}

// 2. 为枚举变体附加数据
enum IpAddr {
    V4(u8, u8, u8, u8), // 元组形式的数据
    V6(String),         // 单值形式的数据
}

// 3. 更复杂的枚举示例
enum Message {
    Quit,
    Move { x: i32, y: i32 },        // 包含结构体
    Write(String),                  // 包含单个字符串
    ChangeColor(i32, i32, i32),     // 包含三个整数
}

// 4. 为枚举实现方法
impl Message {
    fn call(&self) {
        // 方法体可以包含各种逻辑
        match self {
            Message::Quit => println!("退出消息"),
            Message::Move { x, y } => println!("移动到坐标: x={}, y={}", x, y),
            Message::Write(text) => println!("写入消息: {}", text),
            Message::ChangeColor(r, g, b) => println!("更改颜色为 RGB: {}, {}, {}", r, g, b),
        }
    }
}

// 5. Option 枚举
// Option 是 Rust 标准库中的枚举，用于表示可能存在或不存在的值
// Option<T> 有两个变体：Some(T) 表示有值，None 表示没有值
// 定义大致如下：
// enum Option<T> {
//     Some(T),
//     None,
// }

pub fn run() {
    // 6. 使用枚举变体
    let four = IpAddrKind::V4;
    let six = IpAddrKind::V6;
    
    route(four);
    route(six);
    
    // 7. 使用带数据的枚举
    let home = IpAddr::V4(127, 0, 0, 1);
    let loopback = IpAddr::V6(String::from("::1"));
    
    // 8. 使用复杂枚举
    let m1 = Message::Quit;
    let m2 = Message::Move { x: 10, y: 20 };
    let m3 = Message::Write(String::from("Hello, Rust!"));
    let m4 = Message::ChangeColor(255, 0, 0);
    
    // 调用枚举方法
    m1.call();
    m2.call();
    m3.call();
    m4.call();
    
    // 9. 使用 Option 枚举
    let some_number = Some(5);
    let some_string = Some("a string");
    let absent_number: Option<i32> = None;
    
    // Option<T> 和 T 是不同的类型，不能直接进行运算
    let x: i32 = 5;
    // let sum = x + some_number; // 这会导致编译错误
    
    // 需要使用模式匹配或 unwrap 方法来处理 Option
    if let Some(n) = some_number {
        println!("some_number 的值是: {}", n);
    }
    
    // 10. match 表达式
    // match 允许我们根据枚举的变体执行不同的代码
    let dice_roll = 9;
    match dice_roll {
        1 => println!("移动 1 格"),
        2 => println!("移动 2 格"),
        3 => println!("移动 3 格"),
        4 => println!("移动 4 格"),
        5 => println!("移动 5 格"),
        6 => println!("移动 6 格"),
        other => println!("无效的骰子点数: {}", other), // 通配符模式
    }
    
    // 11. match 与枚举
    let some_value = Some(3);
    let none_value: Option<i32> = None;
    
    match some_value {
        Some(i) => println!("找到值: {}", i),
        None => println!("没有值"),
    }
    
    match none_value {
        Some(i) => println!("找到值: {}", i),
        None => println!("没有值"),
    }
    
    // 12. match 中的解构
    let p = Point { x: 0, y: 7 };
    
    match p {
        Point { x, y: 0 } => println!("在 x 轴上，x = {}", x),
        Point { x: 0, y } => println!("在 y 轴上，y = {}", y),
        Point { x, y } => println!("在点 ({}, {})", x, y),
    }
    
    // 13. if let 简洁控制流
    // if let 是 match 的简化形式，用于只关心一种情况的场景
    let config_max = Some(3u8);
    
    // 使用 match
    match config_max {
        Some(max) => println!("配置最大值: {}", max),
        _ => (),
    }
    
    // 使用 if let 更简洁
    if let Some(max) = config_max {
        println!("配置最大值: {}", max);
    }
    
    // 14. if let 和 else
    let mut count = 0;
    let coin = Coin::Quarter(UsState::Alaska);
    
    if let Coin::Quarter(state) = coin {
        println!("这是 {:?} 州的 25 美分硬币!", state);
    } else {
        count += 1;
        println!("不是 25 美分硬币，计数增加到: {}", count);
    }
    
    // 15. 穷尽性检查
    // Rust 的 match 表达式必须是穷尽的，覆盖所有可能的情况
    let five = Some(5);
    let six = plus_one(five);
    let none = plus_one(None);
    
    println!("six = {:?}", six);
    println!("none = {:?}", none);
    
    // 16. 模式匹配中的范围
    let number = 5;
    match number {
        1..=5 => println!("1 到 5 之间的数字"),
        6..=10 => println!("6 到 10 之间的数字"),
        _ => println!("其他数字"),
    }
} // main 函数结束

// 17. 接受枚举作为参数的函数
fn route(ip_kind: IpAddrKind) {
    match ip_kind {
        IpAddrKind::V4 => println!("处理 IPv4 地址"),
        IpAddrKind::V6 => println!("处理 IPv6 地址"),
    }
}

// 18. 用于示例的结构体
struct Point {
    x: i32,
    y: i32,
}

// 19. 用于示例的枚举
#[derive(Debug)]
enum UsState {
    Alabama,
    Alaska,
    // ... 其他州
}

#[derive(Debug)]
enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter(UsState),
}

// 20. 处理 Option 类型的函数
fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(i) => Some(i + 1),
    }
}